!function (e) {
    if ("object" == typeof exports) module.exports = e();
    else if ("function" == typeof define && define.cmd) define(e);
    else {
        var f;
    "undefined" != typeof window ? f = window : "undefined" != typeof global ? f = global : "undefined" != typeof self && (f = self), f.s = e();
    }
}(function () {
    var define, module, exports;
    return (function e(t, n, r) { function s(o, u) { if (!n[o]) { if (!t[o]) { var a = typeof require == "function" && require; if (!u && a) return a(o, !0); if (i) return i(o, !0); throw new Error("Cannot find module '" + o + "'") } var f = n[o] = { exports: {} }; t[o][0].call(f.exports, function (e) { var n = t[o][1][e]; return s(n ? n : e) }, f, f.exports, e, t, n, r) } return n[o].exports } var i = typeof require == "function" && require; for (var o = 0; o < r.length; o++) s(r[o]);
        return s;
    })({
        1: [function (_dereq_, module, exports) {
            var trim = _dereq_('./trim');
            var decap = _dereq_('./decapitalize');

            module.exports = function camelize(str, decapitalize) {
                str = trim(str).replace(/[-_\s]+(.)?/g, function (match, c) {
                    return c ? c.toUpperCase() : "";
                });

                if (decapitalize === true) {
                    return decap(str);
                } else {
                    return str;
                }
            };

        }, { "./decapitalize": 9, "./trim": 60 }], 2: [function (_dereq_, module, exports) {
            var makeString = _dereq_('./helper/makeString');

            module.exports = function capitalize(str) {
                str = makeString(str);
                return str.charAt(0).toUpperCase() + str.slice(1);
            };

        }, { "./helper/makeString": 19 }], 3: [function (_dereq_, module, exports) {
            var makeString = _dereq_('./helper/makeString');

            module.exports = function chars(str) {
                return makeString(str).split('');
            };

        }, { "./helper/makeString": 19 }], 4: [function (_dereq_, module, exports) {
            module.exports = function chop(str, step) {
                if (str == null) return [];
                str = String(str);
                step = ~~step;
                return step > 0 ? str.match(new RegExp('.{1,' + step + '}', 'g')) : [str];
            };

        }, {}], 5: [function (_dereq_, module, exports) {
            var capitalize = _dereq_('./capitalize');
            var camelize = _dereq_('./camelize');
            var makeString = _dereq_('./helper/makeString');

            module.exports = function classify(str) {
                str = makeString(str);
                return capitalize(camelize(str.replace(/[\W_]/g, ' ')).replace(/\s/g, ''));
            };

        }, { "./camelize": 1, "./capitalize": 2, "./helper/makeString": 19 }], 6: [function (_dereq_, module, exports) {
            var trim = _dereq_('./trim');

            module.exports = function clean(str) {
                return trim(str).replace(/\s+/g, ' ');
            };

        }, { "./trim": 60 }], 7: [function (_dereq_, module, exports) {
            var makeString = _dereq_('./helper/makeString');

            module.exports = function (str, substr) {
                str = makeString(str);
                substr = makeString(substr);

                if (str.length === 0 || substr.length === 0) return 0;

                var count = 0,
                  pos = 0,
                  length = substr.length;

                while (true) {
                    pos = str.indexOf(substr, pos);
                    if (pos === -1) break;
                    count++;
                    pos += length;
                }

                return count;
            };

        }, { "./helper/makeString": 19 }], 8: [function (_dereq_, module, exports) {
            var trim = _dereq_('./trim');

            module.exports = function dasherize(str) {
                return trim(str).replace(/([A-Z])/g, '-$1').replace(/[-_\s]+/g, '-').toLowerCase();
            };

        }, { "./trim": 60 }], 9: [function (_dereq_, module, exports) {
            var makeString = _dereq_('./helper/makeString');

            module.exports = function decapitalize(str) {
                str = makeString(str);
                return str.charAt(0).toLowerCase() + str.slice(1);
            };

        }, { "./helper/makeString": 19 }], 10: [function (_dereq_, module, exports) {
            var makeString = _dereq_('./helper/makeString');

            function getIndent(str) {
                var matches = str.match(/^[\s\\t]*/gm);
                var indent = matches[0].length;

                for (var i = 1; i < matches.length; i++) {
                    indent = Math.min(matches[i].length, indent);
                }

                return indent;
            }

            module.exports = function dedent(str, pattern) {
                str = makeString(str);
                var indent = getIndent(str);
                var reg;

                if (indent === 0) return str;

                if (typeof pattern === 'string') {
                    reg = new RegExp('^' + pattern, 'gm');
                } else {
                    reg = new RegExp('^[ \\t]{' + indent + '}', 'gm');
                }

                return str.replace(reg, '');
            };

        }, { "./helper/makeString": 19 }], 11: [function (_dereq_, module, exports) {
            var makeString = _dereq_('./helper/makeString');
            var toPositive = _dereq_('./helper/toPositive');

            module.exports = function endsWith(str, ends, position) {
                str = makeString(str);
                ends = '' + ends;
                if (typeof position == 'undefined') {
                    position = str.length - ends.length;
                } else {
                    position = Math.min(toPositive(position), str.length) - ends.length;
                }
                return position >= 0 && str.indexOf(ends, position) === position;
            };

        }, { "./helper/makeString": 19, "./helper/toPositive": 21 }], 12: [function (_dereq_, module, exports) {
            var makeString = _dereq_('./helper/makeString');
            var escapeChars = _dereq_('./helper/escapeChars');
            var reversedEscapeChars = {};

            for (var key in escapeChars) reversedEscapeChars[escapeChars[key]] = key;
            reversedEscapeChars["'"] = '#39';

            module.exports = function escapeHTML(str) {
                return makeString(str).replace(/[&<>"']/g, function (m) {
                    return '&' + reversedEscapeChars[m] + ';';
                });
            };

        }, { "./helper/escapeChars": 17, "./helper/makeString": 19 }], 13: [function (_dereq_, module, exports) {
            module.exports = function () {
                var result = {};

                for (var prop in this) {
                    if (!this.hasOwnProperty(prop) || prop.match(/^(?:include|contains|reverse|join)$/)) continue;
                    result[prop] = this[prop];
                }

                return result;
            };

        }, {}], 14: [function (_dereq_, module, exports) {
            //  Underscore.string
            //  (c) 2010 Esa-Matti Suuronen <esa-matti aet suuronen dot org>
            //  Underscore.string is freely distributable under the terms of the MIT license.
            //  Documentation: https://github.com/epeli/underscore.string
            //  Some code is borrowed from MooTools and Alexandru Marasteanu.
            //  Version '3.0.2'

            'use strict';

            function s(value) {
                /* jshint validthis: true */
                if (!(this instanceof s)) return new s(value);
                this._wrapped = value;
            }

            s.VERSION = '3.0.2';

            s.isBlank = _dereq_('./isBlank');
            s.stripTags = _dereq_('./stripTags');
            s.capitalize = _dereq_('./capitalize');
            s.decapitalize = _dereq_('./decapitalize');
            s.chop = _dereq_('./chop');
            s.trim = _dereq_('./trim');
            s.clean = _dereq_('./clean');
            s.count = _dereq_('./count');
            s.chars = _dereq_('./chars');
            s.swapCase = _dereq_('./swapCase');
            s.escapeHTML = _dereq_('./escapeHTML');
            s.unescapeHTML = _dereq_('./unescapeHTML');
            s.splice = _dereq_('./splice');
            s.insert = _dereq_('./insert');
            s.replaceAll = _dereq_('./replaceAll');
            s.include = _dereq_('./include');
            s.join = _dereq_('./join');
            s.lines = _dereq_('./lines');
            s.dedent = _dereq_('./dedent');
            s.reverse = _dereq_('./reverse');
            s.startsWith = _dereq_('./startsWith');
            s.endsWith = _dereq_('./endsWith');
            s.pred = _dereq_('./pred');
            s.succ = _dereq_('./succ');
            s.titleize = _dereq_('./titleize');
            s.camelize = _dereq_('./camelize');
            s.underscored = _dereq_('./underscored');
            s.dasherize = _dereq_('./dasherize');
            s.classify = _dereq_('./classify');
            s.humanize = _dereq_('./humanize');
            s.ltrim = _dereq_('./ltrim');
            s.rtrim = _dereq_('./rtrim');
            s.truncate = _dereq_('./truncate');
            s.prune = _dereq_('./prune');
            s.words = _dereq_('./words');
            s.pad = _dereq_('./pad');
            s.lpad = _dereq_('./lpad');
            s.rpad = _dereq_('./rpad');
            s.lrpad = _dereq_('./lrpad');
            s.sprintf = _dereq_('./sprintf');
            s.vsprintf = _dereq_('./vsprintf');
            s.toNumber = _dereq_('./toNumber');
            s.numberFormat = _dereq_('./numberFormat');
            s.strRight = _dereq_('./strRight');
            s.strRightBack = _dereq_('./strRightBack');
            s.strLeft = _dereq_('./strLeft');
            s.strLeftBack = _dereq_('./strLeftBack');
            s.toSentence = _dereq_('./toSentence');
            s.toSentenceSerial = _dereq_('./toSentenceSerial');
            s.slugify = _dereq_('./slugify');
            s.surround = _dereq_('./surround');
            s.quote = _dereq_('./quote');
            s.unquote = _dereq_('./unquote');
            s.repeat = _dereq_('./repeat');
            s.naturalCmp = _dereq_('./naturalCmp');
            s.levenshtein = _dereq_('./levenshtein');
            s.toBoolean = _dereq_('./toBoolean');
            s.exports = _dereq_('./exports');
            s.escapeRegExp = _dereq_('./helper/escapeRegExp');

            // Aliases
            s.strip = s.trim;
            s.lstrip = s.ltrim;
            s.rstrip = s.rtrim;
            s.center = s.lrpad;
            s.rjust = s.lpad;
            s.ljust = s.rpad;
            s.contains = s.include;
            s.q = s.quote;
            s.toBool = s.toBoolean;
            s.camelcase = s.camelize;


            // Implement chaining
            s.prototype = {
                value: function value() {
                    return this._wrapped;
                }
            };

            function fn2method(key, fn) {
                if (typeof fn !== "function") return;
                s.prototype[key] = function () {
                    var args = [this._wrapped].concat(Array.prototype.slice.call(arguments));
                    var res = fn.apply(null, args);
                    // if the result is non-string stop the chain and return the value
                    return typeof res === 'string' ? new s(res) : res;
                };
            }

            // Copy functions to instance methods for chaining
            for (var key in s) fn2method(key, s[key]);

            fn2method("tap", function tap(string, fn) {
                return fn(string);
            });

            function prototype2method(methodName) {
                fn2method(methodName, function (context) {
                    var args = Array.prototype.slice.call(arguments, 1);
                    return String.prototype[methodName].apply(context, args);
                });
            }

            var prototypeMethods = [
              "toUpperCase",
              "toLowerCase",
              "split",
              "replace",
              "slice",
              "substring",
              "substr",
              "concat"
            ];

            for (var key in prototypeMethods) prototype2method(prototypeMethods[key]);


            module.exports = s;

        }, { "./camelize": 1, "./capitalize": 2, "./chars": 3, "./chop": 4, "./classify": 5, "./clean": 6, "./count": 7, "./dasherize": 8, "./decapitalize": 9, "./dedent": 10, "./endsWith": 11, "./escapeHTML": 12, "./exports": 13, "./helper/escapeRegExp": 18, "./humanize": 22, "./include": 23, "./insert": 24, "./isBlank": 25, "./join": 26, "./levenshtein": 27, "./lines": 28, "./lpad": 29, "./lrpad": 30, "./ltrim": 31, "./naturalCmp": 32, "./numberFormat": 33, "./pad": 34, "./pred": 35, "./prune": 36, "./quote": 37, "./repeat": 38, "./replaceAll": 39, "./reverse": 40, "./rpad": 41, "./rtrim": 42, "./slugify": 43, "./splice": 44, "./sprintf": 45, "./startsWith": 46, "./strLeft": 47, "./strLeftBack": 48, "./strRight": 49, "./strRightBack": 50, "./stripTags": 51, "./succ": 52, "./surround": 53, "./swapCase": 54, "./titleize": 55, "./toBoolean": 56, "./toNumber": 57, "./toSentence": 58, "./toSentenceSerial": 59, "./trim": 60, "./truncate": 61, "./underscored": 62, "./unescapeHTML": 63, "./unquote": 64, "./vsprintf": 65, "./words": 66 }], 15: [function (_dereq_, module, exports) {
            var makeString = _dereq_('./makeString');

            module.exports = function adjacent(str, direction) {
                str = makeString(str);
                if (str.length === 0) {
                    return '';
                }
                return str.slice(0, -1) + String.fromCharCode(str.charCodeAt(str.length - 1) + direction);
            };

        }, { "./makeString": 19 }], 16: [function (_dereq_, module, exports) {
            var escapeRegExp = _dereq_('./escapeRegExp');

            module.exports = function defaultToWhiteSpace(characters) {
                if (characters == null)
                    return '\\s';
                else if (characters.source)
                    return characters.source;
                else
                    return '[' + escapeRegExp(characters) + ']';
            };

        }, { "./escapeRegExp": 18 }], 17: [function (_dereq_, module, exports) {
            var escapeChars = {
                lt: '<',
                gt: '>',
                quot: '"',
                amp: '&',
                apos: "'"
            };

            module.exports = escapeChars;

        }, {}], 18: [function (_dereq_, module, exports) {
            var makeString = _dereq_('./makeString');

            module.exports = function escapeRegExp(str) {
                return makeString(str).replace(/([.*+?^=!:${}()|[\]\/\\])/g, '\\$1');
            };

        }, { "./makeString": 19 }], 19: [function (_dereq_, module, exports) {
            /**
             * Ensure some object is a coerced to a string
             **/
            module.exports = function makeString(object) {
                if (object == null) return '';
                return '' + object;
            };

        }, {}], 20: [function (_dereq_, module, exports) {
            module.exports = function strRepeat(str, qty) {
                if (qty < 1) return '';
                var result = '';
                while (qty > 0) {
                    if (qty & 1) result += str;
                    qty >>= 1, str += str;
                }
                return result;
            };

        }, {}], 21: [function (_dereq_, module, exports) {
            module.exports = function toPositive(number) {
                return number < 0 ? 0 : (+number || 0);
            };

        }, {}], 22: [function (_dereq_, module, exports) {
            var capitalize = _dereq_('./capitalize');
            var underscored = _dereq_('./underscored');
            var trim = _dereq_('./trim');

            module.exports = function humanize(str) {
                return capitalize(trim(underscored(str).replace(/_id$/, '').replace(/_/g, ' ')));
            };

        }, { "./capitalize": 2, "./trim": 60, "./underscored": 62 }], 23: [function (_dereq_, module, exports) {
            var makeString = _dereq_('./helper/makeString');

            module.exports = function include(str, needle) {
                if (needle === '') return true;
                return makeString(str).indexOf(needle) !== -1;
            };

        }, { "./helper/makeString": 19 }], 24: [function (_dereq_, module, exports) {
            var splice = _dereq_('./splice');

            module.exports = function insert(str, i, substr) {
                return splice(str, i, 0, substr);
            };

        }, { "./splice": 44 }], 25: [function (_dereq_, module, exports) {
            var makeString = _dereq_('./helper/makeString');

            module.exports = function isBlank(str) {
                return (/^\s*$/).test(makeString(str));
            };

        }, { "./helper/makeString": 19 }], 26: [function (_dereq_, module, exports) {
            var makeString = _dereq_('./helper/makeString');
            var slice = [].slice;

            module.exports = function join() {
                var args = slice.call(arguments),
                  separator = args.shift();

                return args.join(makeString(separator));
            };

        }, { "./helper/makeString": 19 }], 27: [function (_dereq_, module, exports) {
            var makeString = _dereq_('./helper/makeString');

            module.exports = function levenshtein(str1, str2) {
                str1 = makeString(str1);
                str2 = makeString(str2);

                var current = [],
                  prev, value;

                for (var i = 0; i <= str2.length; i++)
                    for (var j = 0; j <= str1.length; j++) {
                        if (i && j)
                            if (str1.charAt(j - 1) === str2.charAt(i - 1))
                                value = prev;
                            else
                                value = Math.min(current[j], current[j - 1], prev) + 1;
                        else
                            value = i + j;

                        prev = current[j];
                        current[j] = value;
                    }

                return current.pop();
            };

        }, { "./helper/makeString": 19 }], 28: [function (_dereq_, module, exports) {
            module.exports = function lines(str) {
                if (str == null) return [];
                return String(str).split(/\r?\n/);
            };

        }, {}], 29: [function (_dereq_, module, exports) {
            var pad = _dereq_('./pad');

            module.exports = function lpad(str, length, padStr) {
                return pad(str, length, padStr);
            };

        }, { "./pad": 34 }], 30: [function (_dereq_, module, exports) {
            var pad = _dereq_('./pad');

            module.exports = function lrpad(str, length, padStr) {
                return pad(str, length, padStr, 'both');
            };

        }, { "./pad": 34 }], 31: [function (_dereq_, module, exports) {
            var makeString = _dereq_('./helper/makeString');
            var defaultToWhiteSpace = _dereq_('./helper/defaultToWhiteSpace');
            var nativeTrimLeft = String.prototype.trimLeft;

            module.exports = function ltrim(str, characters) {
                str = makeString(str);
                if (!characters && nativeTrimLeft) return nativeTrimLeft.call(str);
                characters = defaultToWhiteSpace(characters);
                return str.replace(new RegExp('^' + characters + '+'), '');
            };

        }, { "./helper/defaultToWhiteSpace": 16, "./helper/makeString": 19 }], 32: [function (_dereq_, module, exports) {
            module.exports = function naturalCmp(str1, str2) {
                if (str1 == str2) return 0;
                if (!str1) return -1;
                if (!str2) return 1;

                var cmpRegex = /(\.\d+)|(\d+)|(\D+)/g,
                  tokens1 = String(str1).match(cmpRegex),
                  tokens2 = String(str2).match(cmpRegex),
                  count = Math.min(tokens1.length, tokens2.length);

                for (var i = 0; i < count; i++) {
                    var a = tokens1[i],
                      b = tokens2[i];

                    if (a !== b) {
                        var num1 = +a;
                        var num2 = +b;
                        if (num1 === num1 && num2 === num2) {
                            return num1 > num2 ? 1 : -1;
                        }
                        return a < b ? -1 : 1;
                    }
                }

                if (tokens1.length != tokens2.length)
                    return tokens1.length - tokens2.length;

                return str1 < str2 ? -1 : 1;
            };

        }, {}], 33: [function (_dereq_, module, exports) {
            module.exports = function numberFormat(number, dec, dsep, tsep) {
                if (isNaN(number) || number == null) return '';

                number = number.toFixed(~~dec);
                tsep = typeof tsep == 'string' ? tsep : ',';

                var parts = number.split('.'),
                  fnums = parts[0],
                  decimals = parts[1] ? (dsep || '.') + parts[1] : '';

                return fnums.replace(/(\d)(?=(?:\d{3})+$)/g, '$1' + tsep) + decimals;
            };

        }, {}], 34: [function (_dereq_, module, exports) {
            var makeString = _dereq_('./helper/makeString');
            var strRepeat = _dereq_('./helper/strRepeat');

            module.exports = function pad(str, length, padStr, type) {
                str = makeString(str);
                length = ~~length;

                var padlen = 0;

                if (!padStr)
                    padStr = ' ';
                else if (padStr.length > 1)
                    padStr = padStr.charAt(0);

                switch (type) {
                    case 'right':
                        padlen = length - str.length;
                        return str + strRepeat(padStr, padlen);
                    case 'both':
                        padlen = length - str.length;
                        return strRepeat(padStr, Math.ceil(padlen / 2)) + str + strRepeat(padStr, Math.floor(padlen / 2));
                    default: // 'left'
                        padlen = length - str.length;
                        return strRepeat(padStr, padlen) + str;
                }
            };

        }, { "./helper/makeString": 19, "./helper/strRepeat": 20 }], 35: [function (_dereq_, module, exports) {
            var adjacent = _dereq_('./helper/adjacent');

            module.exports = function succ(str) {
                return adjacent(str, -1);
            };

        }, { "./helper/adjacent": 15 }], 36: [function (_dereq_, module, exports) {
            /**
             * _s.prune: a more elegant version of truncate
             * prune extra chars, never leaving a half-chopped word.
             * @author github.com/rwz
             */
            var makeString = _dereq_('./helper/makeString');
            var rtrim = _dereq_('./rtrim');

            module.exports = function prune(str, length, pruneStr) {
                str = makeString(str);
                length = ~~length;
                pruneStr = pruneStr != null ? String(pruneStr) : '...';

                if (str.length <= length) return str;

                var tmpl = function (c) {
                    return c.toUpperCase() !== c.toLowerCase() ? 'A' : ' ';
                },
                  template = str.slice(0, length + 1).replace(/.(?=\W*\w*$)/g, tmpl); // 'Hello, world' -> 'HellAA AAAAA'

                if (template.slice(template.length - 2).match(/\w\w/))
                    template = template.replace(/\s*\S+$/, '');
                else
                    template = rtrim(template.slice(0, template.length - 1));

                return (template + pruneStr).length > str.length ? str : str.slice(0, template.length) + pruneStr;
            };

        }, { "./helper/makeString": 19, "./rtrim": 42 }], 37: [function (_dereq_, module, exports) {
            var surround = _dereq_('./surround');

            module.exports = function quote(str, quoteChar) {
                return surround(str, quoteChar || '"');
            };

        }, { "./surround": 53 }], 38: [function (_dereq_, module, exports) {
            var makeString = _dereq_('./helper/makeString');
            var strRepeat = _dereq_('./helper/strRepeat');

            module.exports = function repeat(str, qty, separator) {
                str = makeString(str);

                qty = ~~qty;

                // using faster implementation if separator is not needed;
                if (separator == null) return strRepeat(str, qty);

                // this one is about 300x slower in Google Chrome
                for (var repeat = []; qty > 0; repeat[--qty] = str) { }
                return repeat.join(separator);
            };

        }, { "./helper/makeString": 19, "./helper/strRepeat": 20 }], 39: [function (_dereq_, module, exports) {
            var makeString = _dereq_('./helper/makeString');

            module.exports = function replaceAll(str, find, replace, ignorecase) {
                var flags = (ignorecase === true) ? 'gi' : 'g';
                var reg = new RegExp(find, flags);

                return makeString(str).replace(reg, replace);
            };

        }, { "./helper/makeString": 19 }], 40: [function (_dereq_, module, exports) {
            var chars = _dereq_('./chars');

            module.exports = function reverse(str) {
                return chars(str).reverse().join('');
            };

        }, { "./chars": 3 }], 41: [function (_dereq_, module, exports) {
            var pad = _dereq_('./pad');

            module.exports = function rpad(str, length, padStr) {
                return pad(str, length, padStr, 'right');
            };

        }, { "./pad": 34 }], 42: [function (_dereq_, module, exports) {
            var makeString = _dereq_('./helper/makeString');
            var defaultToWhiteSpace = _dereq_('./helper/defaultToWhiteSpace');
            var nativeTrimRight = String.prototype.trimRight;

            module.exports = function rtrim(str, characters) {
                str = makeString(str);
                if (!characters && nativeTrimRight) return nativeTrimRight.call(str);
                characters = defaultToWhiteSpace(characters);
                return str.replace(new RegExp(characters + '+$'), '');
            };

        }, { "./helper/defaultToWhiteSpace": 16, "./helper/makeString": 19 }], 43: [function (_dereq_, module, exports) {
            var makeString = _dereq_('./helper/makeString');
            var defaultToWhiteSpace = _dereq_('./helper/defaultToWhiteSpace');
            var trim = _dereq_('./trim');
            var dasherize = _dereq_('./dasherize');

            module.exports = function slugify(str) {
                var from = "ąàáäâãåæăćčĉęèéëêĝĥìíïîĵłľńňòóöőôõðøśșšŝťțŭùúüűûñÿýçżźž",
                    to = "aaaaaaaaaccceeeeeghiiiijllnnoooooooossssttuuuuuunyyczzz",
                    regex = new RegExp(defaultToWhiteSpace(from), 'g');

                str = makeString(str).toLowerCase().replace(regex, function (c) {
                    var index = from.indexOf(c);
                    return to.charAt(index) || '-';
                });

                return trim(dasherize(str.replace(/[^\w\s-]/g, '-')), '-');
            };

        }, { "./dasherize": 8, "./helper/defaultToWhiteSpace": 16, "./helper/makeString": 19, "./trim": 60 }], 44: [function (_dereq_, module, exports) {
            var chars = _dereq_('./chars');

            module.exports = function splice(str, i, howmany, substr) {
                var arr = chars(str);
                arr.splice(~~i, ~~howmany, substr);
                return arr.join('');
            };

        }, { "./chars": 3 }], 45: [function (_dereq_, module, exports) {
            // sprintf() for JavaScript 0.7-beta1
            // http://www.diveintojavascript.com/projects/javascript-sprintf
            //
            // Copyright (c) Alexandru Marasteanu <alexaholic [at) gmail (dot] com>
            // All rights reserved.
            var strRepeat = _dereq_('./helper/strRepeat');
            var toString = Object.prototype.toString;
            var sprintf = (function () {
                function get_type(variable) {
                    return toString.call(variable).slice(8, -1).toLowerCase();
                }

                var str_repeat = strRepeat;

                var str_format = function () {
                    if (!str_format.cache.hasOwnProperty(arguments[0])) {
                        str_format.cache[arguments[0]] = str_format.parse(arguments[0]);
                    }
                    return str_format.format.call(null, str_format.cache[arguments[0]], arguments);
                };

                str_format.format = function (parse_tree, argv) {
                    var cursor = 1, tree_length = parse_tree.length, node_type = '', arg, output = [], i, k, match, pad, pad_character, pad_length;
                    for (i = 0; i < tree_length; i++) {
                        node_type = get_type(parse_tree[i]);
                        if (node_type === 'string') {
                            output.push(parse_tree[i]);
                        }
                        else if (node_type === 'array') {
                            match = parse_tree[i]; // convenience purposes only
                            if (match[2]) { // keyword argument
                                arg = argv[cursor];
                                for (k = 0; k < match[2].length; k++) {
                                    if (!arg.hasOwnProperty(match[2][k])) {
                                        throw new Error(sprintf('[_.sprintf] property "%s" does not exist', match[2][k]));
                                    }
                                    arg = arg[match[2][k]];
                                }
                            } else if (match[1]) { // positional argument (explicit)
                                arg = argv[match[1]];
                            }
                            else { // positional argument (implicit)
                                arg = argv[cursor++];
                            }

                            if (/[^s]/.test(match[8]) && (get_type(arg) != 'number')) {
                                throw new Error(sprintf('[_.sprintf] expecting number but found %s', get_type(arg)));
                            }
                            switch (match[8]) {
                                case 'b': arg = arg.toString(2); break;
                                case 'c': arg = String.fromCharCode(arg); break;
                                case 'd': arg = parseInt(arg, 10); break;
                                case 'e': arg = match[7] ? arg.toExponential(match[7]) : arg.toExponential(); break;
                                case 'f': arg = match[7] ? parseFloat(arg).toFixed(match[7]) : parseFloat(arg); break;
                                case 'o': arg = arg.toString(8); break;
                                case 's': arg = ((arg = String(arg)) && match[7] ? arg.substring(0, match[7]) : arg); break;
                                case 'u': arg = Math.abs(arg); break;
                                case 'x': arg = arg.toString(16); break;
                                case 'X': arg = arg.toString(16).toUpperCase(); break;
                            }
                            arg = (/[def]/.test(match[8]) && match[3] && arg >= 0 ? '+' + arg : arg);
                            pad_character = match[4] ? match[4] == '0' ? '0' : match[4].charAt(1) : ' ';
                            pad_length = match[6] - String(arg).length;
                            pad = match[6] ? str_repeat(pad_character, pad_length) : '';
                            output.push(match[5] ? arg + pad : pad + arg);
                        }
                    }
                    return output.join('');
                };

                str_format.cache = {};

                str_format.parse = function (fmt) {
                    var _fmt = fmt, match = [], parse_tree = [], arg_names = 0;
                    while (_fmt) {
                        if ((match = /^[^\x25]+/.exec(_fmt)) !== null) {
                            parse_tree.push(match[0]);
                        }
                        else if ((match = /^\x25{2}/.exec(_fmt)) !== null) {
                            parse_tree.push('%');
                        }
                        else if ((match = /^\x25(?:([1-9]\d*)\$|\(([^\)]+)\))?(\+)?(0|'[^$])?(-)?(\d+)?(?:\.(\d+))?([b-fosuxX])/.exec(_fmt)) !== null) {
                            if (match[2]) {
                                arg_names |= 1;
                                var field_list = [], replacement_field = match[2], field_match = [];
                                if ((field_match = /^([a-z_][a-z_\d]*)/i.exec(replacement_field)) !== null) {
                                    field_list.push(field_match[1]);
                                    while ((replacement_field = replacement_field.substring(field_match[0].length)) !== '') {
                                        if ((field_match = /^\.([a-z_][a-z_\d]*)/i.exec(replacement_field)) !== null) {
                                            field_list.push(field_match[1]);
                                        }
                                        else if ((field_match = /^\[(\d+)\]/.exec(replacement_field)) !== null) {
                                            field_list.push(field_match[1]);
                                        }
                                        else {
                                            throw new Error('[_.sprintf] huh?');
                                        }
                                    }
                                }
                                else {
                                    throw new Error('[_.sprintf] huh?');
                                }
                                match[2] = field_list;
                            }
                            else {
                                arg_names |= 2;
                            }
                            if (arg_names === 3) {
                                throw new Error('[_.sprintf] mixing positional and named placeholders is not (yet) supported');
                            }
                            parse_tree.push(match);
                        }
                        else {
                            throw new Error('[_.sprintf] huh?');
                        }
                        _fmt = _fmt.substring(match[0].length);
                    }
                    return parse_tree;
                };

                return str_format;
            })();

            module.exports = sprintf;

        }, { "./helper/strRepeat": 20 }], 46: [function (_dereq_, module, exports) {
            var makeString = _dereq_('./helper/makeString');
            var toPositive = _dereq_('./helper/toPositive');

            module.exports = function startsWith(str, starts, position) {
                str = makeString(str);
                starts = '' + starts;
                position = position == null ? 0 : Math.min(toPositive(position), str.length);
                return str.lastIndexOf(starts, position) === position;
            };

        }, { "./helper/makeString": 19, "./helper/toPositive": 21 }], 47: [function (_dereq_, module, exports) {
            var makeString = _dereq_('./helper/makeString');

            module.exports = function strLeft(str, sep) {
                str = makeString(str);
                sep = makeString(sep);
                var pos = !sep ? -1 : str.indexOf(sep);
                return ~pos ? str.slice(0, pos) : str;
            };

        }, { "./helper/makeString": 19 }], 48: [function (_dereq_, module, exports) {
            var makeString = _dereq_('./helper/makeString');

            module.exports = function strLeftBack(str, sep) {
                str = makeString(str);
                sep = makeString(sep);
                var pos = str.lastIndexOf(sep);
                return ~pos ? str.slice(0, pos) : str;
            };

        }, { "./helper/makeString": 19 }], 49: [function (_dereq_, module, exports) {
            var makeString = _dereq_('./helper/makeString');

            module.exports = function strRight(str, sep) {
                str = makeString(str);
                sep = makeString(sep);
                var pos = !sep ? -1 : str.indexOf(sep);
                return ~pos ? str.slice(pos + sep.length, str.length) : str;
            };

        }, { "./helper/makeString": 19 }], 50: [function (_dereq_, module, exports) {
            var makeString = _dereq_('./helper/makeString');

            module.exports = function strRightBack(str, sep) {
                str = makeString(str);
                sep = makeString(sep);
                var pos = !sep ? -1 : str.lastIndexOf(sep);
                return ~pos ? str.slice(pos + sep.length, str.length) : str;
            };

        }, { "./helper/makeString": 19 }], 51: [function (_dereq_, module, exports) {
            var makeString = _dereq_('./helper/makeString');

            module.exports = function stripTags(str) {
                return makeString(str).replace(/<\/?[^>]+>/g, '');
            };

        }, { "./helper/makeString": 19 }], 52: [function (_dereq_, module, exports) {
            var adjacent = _dereq_('./helper/adjacent');

            module.exports = function succ(str) {
                return adjacent(str, 1);
            };

        }, { "./helper/adjacent": 15 }], 53: [function (_dereq_, module, exports) {
            module.exports = function surround(str, wrapper) {
                return [wrapper, str, wrapper].join('');
            };

        }, {}], 54: [function (_dereq_, module, exports) {
            var makeString = _dereq_('./helper/makeString');

            module.exports = function swapCase(str) {
                return makeString(str).replace(/\S/g, function (c) {
                    return c === c.toUpperCase() ? c.toLowerCase() : c.toUpperCase();
                });
            };

        }, { "./helper/makeString": 19 }], 55: [function (_dereq_, module, exports) {
            var makeString = _dereq_('./helper/makeString');

            module.exports = function titleize(str) {
                return makeString(str).toLowerCase().replace(/(?:^|\s|-)\S/g, function (c) {
                    return c.toUpperCase();
                });
            };

        }, { "./helper/makeString": 19 }], 56: [function (_dereq_, module, exports) {
            var trim = _dereq_('./trim');

            function boolMatch(s, matchers) {
                var i, matcher, down = s.toLowerCase();
                matchers = [].concat(matchers);
                for (i = 0; i < matchers.length; i += 1) {
                    matcher = matchers[i];
                    if (!matcher) continue;
                    if (matcher.test && matcher.test(s)) return true;
                    if (matcher.toLowerCase() === down) return true;
                }
            }

            module.exports = function toBoolean(str, trueValues, falseValues) {
                if (typeof str === "number") str = "" + str;
                if (typeof str !== "string") return !!str;
                str = trim(str);
                if (boolMatch(str, trueValues || ["true", "1"])) return true;
                if (boolMatch(str, falseValues || ["false", "0"])) return false;
            };

        }, { "./trim": 60 }], 57: [function (_dereq_, module, exports) {
            var trim = _dereq_('./trim');
            var parseNumber = function (source) {
                return source * 1 || 0;
            };

            module.exports = function toNumber(num, precision) {
                if (num == null) return 0;
                var factor = Math.pow(10, isFinite(precision) ? precision : 0);
                return Math.round(num * factor) / factor;
            };

        }, { "./trim": 60 }], 58: [function (_dereq_, module, exports) {
            var rtrim = _dereq_('./rtrim');

            module.exports = function toSentence(array, separator, lastSeparator, serial) {
                separator = separator || ', ';
                lastSeparator = lastSeparator || ' and ';
                var a = array.slice(),
                  lastMember = a.pop();

                if (array.length > 2 && serial) lastSeparator = rtrim(separator) + lastSeparator;

                return a.length ? a.join(separator) + lastSeparator + lastMember : lastMember;
            };

        }, { "./rtrim": 42 }], 59: [function (_dereq_, module, exports) {
            var toSentence = _dereq_('./toSentence');

            module.exports = function toSentenceSerial(array, sep, lastSep) {
                return toSentence(array, sep, lastSep, true);
            };

        }, { "./toSentence": 58 }], 60: [function (_dereq_, module, exports) {
            var makeString = _dereq_('./helper/makeString');
            var defaultToWhiteSpace = _dereq_('./helper/defaultToWhiteSpace');
            var nativeTrim = String.prototype.trim;

            module.exports = function trim(str, characters) {
                str = makeString(str);
                if (!characters && nativeTrim) return nativeTrim.call(str);
                characters = defaultToWhiteSpace(characters);
                return str.replace(new RegExp('^' + characters + '+|' + characters + '+$', 'g'), '');
            };

        }, { "./helper/defaultToWhiteSpace": 16, "./helper/makeString": 19 }], 61: [function (_dereq_, module, exports) {
            var makeString = _dereq_('./helper/makeString');

            module.exports = function truncate(str, length, truncateStr) {
                str = makeString(str);
                truncateStr = truncateStr || '...';
                length = ~~length;
                return str.length > length ? str.slice(0, length) + truncateStr : str;
            };

        }, { "./helper/makeString": 19 }], 62: [function (_dereq_, module, exports) {
            var trim = _dereq_('./trim');

            module.exports = function underscored(str) {
                return trim(str).replace(/([a-z\d])([A-Z]+)/g, '$1_$2').replace(/[-\s]+/g, '_').toLowerCase();
            };

        }, { "./trim": 60 }], 63: [function (_dereq_, module, exports) {
            var makeString = _dereq_('./helper/makeString');
            var escapeChars = _dereq_('./helper/escapeChars');

            module.exports = function unescapeHTML(str) {
                return makeString(str).replace(/\&([^;]+);/g, function (entity, entityCode) {
                    var match;

                    if (entityCode in escapeChars) {
                        return escapeChars[entityCode];
                    } else if (match = entityCode.match(/^#x([\da-fA-F]+)$/)) {
                        return String.fromCharCode(parseInt(match[1], 16));
                    } else if (match = entityCode.match(/^#(\d+)$/)) {
                        return String.fromCharCode(~~match[1]);
                    } else {
                        return entity;
                    }
                });
            };

        }, { "./helper/escapeChars": 17, "./helper/makeString": 19 }], 64: [function (_dereq_, module, exports) {
            module.exports = function unquote(str, quoteChar) {
                quoteChar = quoteChar || '"';
                if (str[0] === quoteChar && str[str.length - 1] === quoteChar)
                    return str.slice(1, str.length - 1);
                else return str;
            };

        }, {}], 65: [function (_dereq_, module, exports) {
            var sprintf = _dereq_('./sprintf');

            module.exports = function vsprintf(fmt, argv) {
                argv.unshift(fmt);
                return sprintf.apply(null, argv);
            };

        }, { "./sprintf": 45 }], 66: [function (_dereq_, module, exports) {
            var isBlank = _dereq_('./isBlank');
            var trim = _dereq_('./trim');

            module.exports = function words(str, delimiter) {
                if (isBlank(str)) return [];
                return trim(str, delimiter).split(delimiter || /\s+/);
            };

        }, { "./isBlank": 25, "./trim": 60 }]
    }, {}, [14])
    (14)
});